#!/usr/bin/perl

# $Id: Collection.pm 157 2009-02-07 10:56:52Z mail@tobyinkster.co.uk $

=head1 NAME

Swignition::DataModel::Collection - Represents an RDF literal.

=cut

package Swignition::DataModel::Collection;

use Swignition::DataModel::NodeWithInternalTriples;
use Swignition::MagicString;

use constant TRUE      =>  1;
use constant FALSE     =>  0;
use strict;

our @ISA = ("Swignition::DataModel::NodeWithInternalTriples");
our $VERSION = '0.1';

sub new
{
	my $class = shift;
	my $model = shift;
	my $type  = shift;
	
	my $this = Swignition::DataModel::Node::new(__PACKAGE__, $model);

	$this->{'_'}->{'collection'} = [];
	$this->{'_'}->{'collection_type'} = 'List'; # default
	
	$this->{'_'}->{'cached'} = {};
	
	$this->set_collection_type($type);
	
	return $this;
}

sub collection_type
{
	my $this = shift;
	return $this->{'_'}->{'collection_type'};
}

sub set_collection_type
{
	my $this = shift;
	my $type = shift;
	
	$this->{'_'}->{'collection_type'} = $type
		if ($type =~ /^(Container|Bag|Seq|Alt|List)$/);

	return $this;
}

sub add_node
{
	my $this = shift;
	my $node = shift;
	
	push @{ $this->{'_'}->{'collection'} }, $node;
	$this->{'_'}->{'cached'} = {};
	
	return $this;
}

sub _get_triples
{
	my $this = shift;
	my @triples;
	my $rdftype_predicate = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type';

	return $this->{'_'}->{'cached'}->{ $this->collection_type }
		if defined $this->{'_'}->{'cached'}->{ $this->collection_type };

	if ( $this->collection_type eq 'List' )
	{
		my $list_node = $this;
		
		for (my $i = 0; defined $this->{'_'}->{'collection'}->[$i]; $i++)
		{
			push @triples,
				Swignition::DataModel::Triple->new(
					$this->model,
					$list_node,
					Swignition::DataModel::Resource->new($this->model, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'),
					Swignition::DataModel::Resource->new($this->model, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#List')
				);
			push @triples,
				Swignition::DataModel::Triple->new(
					$this->model,
					$list_node,
					Swignition::DataModel::Resource->new($this->model, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#first'),
					$this->{'_'}->{'collection'}->[$i]
				);
			
			if (defined $this->{'_'}->{'collection'}->[$i + 1])
			{
				my $new_list_node = Swignition::DataModel::BlankNode->new($this->model);
				push @triples,
					Swignition::DataModel::Triple->new(
						$this->model,
						$list_node,
						Swignition::DataModel::Resource->new($this->model, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest'),
						$new_list_node
					);
				$list_node = $new_list_node;
			}
			else
			{
				push @triples,
					Swignition::DataModel::Triple->new(
						$this->model,
						$list_node,
						Swignition::DataModel::Resource->new($this->model, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest'),
						Swignition::DataModel::Resource->new($this->model, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil')
					);
			}
		}
	}
	
	else
	{
		my $rdftype = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
			. $this->collection_type;
		$rdftype = 'http://www.w3.org/2000/01/rdf-schema#Container'
			if $this->collection_type eq 'Container';
	
		push @triples,
			Swignition::DataModel::Triple->new(
				$this->model,
				$this,
				Swignition::DataModel::Resource->new($this->model, $rdftype_predicate),
				Swignition::DataModel::Resource->new($this->model, $rdftype)
			);
		
		for (my $i = 0; defined $this->{'_'}->{'collection'}->[$i]; $i++)
		{
			push @triples,
				Swignition::DataModel::Triple->new(
					$this->model,
					$this,
					Swignition::DataModel::Resource->new($this->model, 'http://www.w3.org/1999/02/22-rdf-syntax-ns#_'.($i+1)),
					$this->{'_'}->{'collection'}->[$i]
				);
		}
	}
	
	$this->{'_'}->{'cached'}->{ $this->collection_type } = \@triples;
	return \@triples;
}

sub _get_nodes
{
	my $rv      = {};
	my $triples = _get_triples(@_);
	foreach my $t (@$triples)
	{
		$rv->{ $t->subject->internal_id } =   $t->subject;
		$rv->{ $t->predicate->internal_id } = $t->predicate;
		$rv->{ $t->object->internal_id } =    $t->object;
	}
	my @rva = values %$rv;
	return \@rva;
}

1;
